﻿using Caliburn.Micro;
using MusicExplorer.Common;
using MusicExplorer.Model;
using MusicExplorer.ViewModels;
using MyToolkit.Multimedia;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using WinRTXamlToolkit.AwaitableUI;

// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238

namespace MusicExplorer.Views
{
    /// <summary>
    /// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame.
    /// </summary>
    public sealed partial class RootView : Page
    {
        private readonly DispatcherTimer m_timer;
        private bool m_sliderPressed = false;
        public RootView()
        {
            this.InitializeComponent();

            m_timer = new DispatcherTimer();
            this.DataContextChanged += RootView_DataContextChanged;
        }

        private bool m_eventsLoaded;
        void RootView_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
        {
            if (!m_eventsLoaded && DataContext != null && DataContext is RootViewModel)
            {
                ((RootViewModel)DataContext).PlayCurrentMedia += RootView_PlayCurrentMedia;
                ((RootViewModel)DataContext).StopCurrentMedia += RootView_StopCurrentMedia;
                m_eventsLoaded = true;
            }
        }

        async void RootView_StopCurrentMedia(object sender, TrackEventArgs e)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                //webView.NavigateToString(string.Empty);
                mediaElement.Stop();
            });
        }

        private string m_youtubeHtml;
        private async Task LoadYoutubeHtmlAsync()
        {
            var currentAssembly = typeof(RootView).GetTypeInfo().Assembly;
            var assemblyName = currentAssembly.FullName.Split(',')[0];
            var stream = currentAssembly.GetManifestResourceStream(string.Format(
                "{0}.Resources.Html.Youtube.html", assemblyName));
            using(var reader = new StreamReader(stream))
                m_youtubeHtml = await reader.ReadToEndAsync();
        }

        HttpWebRequest request;
        TrackType m_currentTrackType;
        bool m_firstTimeYoutube = true;
        async void RootView_PlayCurrentMedia(object sender, TrackEventArgs e)
        {
            m_currentTrackType = e.Track.Type;
            Uri uriToPlay = null;
            switch(e.Track.Type)
            {
                case Model.TrackType.Classic:
                    if (!string.IsNullOrEmpty(e.Track.Mp3))
                    {
                        uriToPlay = new Uri(e.Track.Mp3);
                        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                        {
                            progressTrack.IsActive = true;
                            mediaElement.IsFullWindow = false;
                            mediaElement.Source = uriToPlay;
                        });
                    }
                    break;
                case Model.TrackType.Youtube:
                    //if (string.IsNullOrEmpty(m_youtubeHtml)) await LoadYoutubeHtmlAsync();
                    //var trackHtml = m_youtubeHtml.Replace("#TRACK_ID#", e.Track.Id);
                    //webView.NavigateToString(trackHtml);
                    var youtubeUri = await MyToolkit.Multimedia.YouTube.GetVideoUriAsync(e.Track.Id, MyToolkit.Multimedia.YouTubeQuality.Quality1080P);
                    uriToPlay = youtubeUri.Uri;
                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        progressTrack.IsActive = true;
                        mediaElement.IsFullWindow = false;
                        mediaElement.Source = uriToPlay;
                    });
                    break;
                case Model.TrackType.Soundcloud:
                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        progressTrack.IsActive = true;
                    });
                    if(request != null)
                    {
                        request.Abort();
                    }
                    request = WebRequest.Create(e.Track.SoundcloudStream) as HttpWebRequest;
                    request.Method = "GET";
                    var response = await request.GetResponseAsync();

                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        mediaElement.Source = response.ResponseUri;
                    });
                    break;
                default:
                    throw new NotImplementedException("Not implemented type");
            }
            //if (string.IsNullOrEmpty(e.Track.Mp3))
            //{
            //    var youtubeUri = await MyToolkit.Multimedia.YouTube.GetVideoUriAsync(e.Track.Id, MyToolkit.Multimedia.YouTubeQuality.Quality1080P);
            //    uriToPlay = youtubeUri.Uri;
            //}
            //else
            //{
            //    uriToPlay = new Uri(e.Track.Mp3);
            //}
        }

        private void Frame_Loaded(object sender, RoutedEventArgs e)
        {
            var frame = (Frame)sender;
            var container = IoC.Get<WinRTContainer>();
            container.RegisterInstance(typeof(INavigationService), null, new FrameAdapter(frame));
        }

        private void webView_LoadCompleted(object sender, NavigationEventArgs e)
        {
            if (m_currentTrackType == TrackType.Youtube)
                progressTrack.IsActive = false;
        }

        private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
        {
            progressTrack.IsActive = false;
            mediaElement.Play();
            m_timer.Stop();
            m_sliderPressed = false;
            timelineSlider.Value = 0.0;
            timelineSlider.Maximum = (int)Math.Round(
                mediaElement.NaturalDuration.TimeSpan.TotalSeconds,
                MidpointRounding.AwayFromZero);
            timelineSlider.StepFrequency = (int)Math.Max(1, (Math.Round(timelineSlider.Maximum / 100)));

            m_timer.Interval = TimeSpan.FromSeconds(timelineSlider.StepFrequency);
            m_timer.Tick += m_timer_Tick;
            m_timer.Start();
        }

        void m_timer_Tick(object sender, object e)
        {
            if(!m_sliderPressed)
                timelineSlider.Value = mediaElement.Position.TotalSeconds;
        }

        private void mediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            progressTrack.IsActive = false;
            m_timer.Stop();
            timelineSlider.Value = 0.0;
        }

        private void timelineSlider_PointerEntered(object sender, PointerRoutedEventArgs e)
        {
            if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse)
                m_sliderPressed = true;
        }

        private void timelineSlider_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
        {
            mediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
            m_sliderPressed = false;
        }

        private void Play_Click(object sender, RoutedEventArgs e)
        {
            m_timer.Start();
            mediaElement.Play();
        }

        private void Pause_Click(object sender, RoutedEventArgs e)
        {
            m_timer.Stop();
            mediaElement.Pause();
        }
    }
}
